/***************************************************************************
*                                                                         *
*   This file is part of the Fotowall project,                            *
*       http://code.google.com/p/fotowall                                 *
*                                                                         *
*   Copyright (C) 2009 by Enrico Ros <enrico.ros@gmail.com>               *
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
 * ----------------------------------------------------------------------- *
 *																		   *
 *	Modifications for FotoKinect, Spring 2011 by Gianna Badiali,		   *
 *                                                   Gabriel Fernandez,	   *
 *                                                   Kelsey Tripp, and     *
 *                                                   Sam Swarr             *
 *																		   *
 ***************************************************************************/

#include "MetaXmlReader.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QTimer>
#include <QUrl>

#define METAXML_BASE_URL "http://www.enricoros.com/opensource/fotowall/.meta"
#define NETWORK_TIMEOUT 10000

/* pre-0.8.0 used this settings:
#define OLD_CHECK_URL "http://code.google.com/p/fotowall/"
#define OLD_MAGIC_TOKEN "Last version is "
#define OLD_DOWNLOADS_URL "http://code.google.com/p/fotowall/downloads/list"
*/

using namespace MetaXml;

Reader_1::Reader_1(const QByteArray & data)
	: QXmlStreamReader(data)
{
	read();
}

void Reader_1::read()
{
	while (!atEnd()) {
		readNext();
		if (isEndElement())
			break;
		if (isStartElement()) {
			if (name() == QLatin1String("fotowall-meta"))
				continue;
			else if (name() == QLatin1String("releases"))
				readReleases();
			else if (name() == QLatin1String("websites"))
				readWebsites();
			else
				readElementText();
		}
	}
}

void Reader_1::readReleases()
{
	releases.clear();
	while (!atEnd()) {
		readNext();
		if (isEndElement())
			break;
		if (isStartElement()) {
			if (name() == QLatin1String("release"))
				releases.append(readRelease());
			else
				readElementText();
		}
	}
}

Release Reader_1::readRelease()
{
	Release r;
	r.name = attributes().value("name").toString();
	while (!atEnd()) {
		readNext();
		if (isEndElement())
			break;
		if (isStartElement()) {
			if (name() == QLatin1String("version"))
				r.version = readElementText();
			else if (name() == QLatin1String("download-url"))
				r.url = readElementText();
			else
				readElementText();
		}
	}
	return r;
}

void Reader_1::readWebsites()
{
	websites.clear();
	while (!atEnd()) {
		readNext();
		if (isEndElement())
			break;
		if (isStartElement()) {
			if (name() == QLatin1String("homepage") || name() == QLatin1String("site")) {
				Website w;
				w.name = attributes().value("name").toString();
				w.url = readElementText();
				if (name() == QLatin1String("homepage"))
					websites.prepend(w);
				else
					websites.append(w);
			} else
				readElementText();
		}
	}
}


/* Connector */

Q_GLOBAL_STATIC(Connector, connectorInstance);
Connector * Connector::instance()
{
	return connectorInstance();
}

Connector::Connector()
	: m_nam(new QNetworkAccessManager)
	, m_reader(0)
{
	QNetworkRequest request(QUrl(METAXML_BASE_URL));
	QNetworkReply * reply = m_nam->get(request);
	connect(reply, SIGNAL(finished()), this, SLOT(slotGotReply()));
	QTimer::singleShot(NETWORK_TIMEOUT, this, SLOT(slotTimeOut()));
}

bool Connector::hasDone() const
{
	return !m_nam;
}

bool Connector::isValid() const
{
	return m_reader;
}

const Reader_1 * Connector::reader() const
{
	return m_reader;
}

void Connector::slotGotReply()
{
	// dispose the QNAM
	if (!m_nam)
		return;
	m_nam->deleteLater();
	m_nam = 0;

	// get the data from the network reply
	QNetworkReply * reply = static_cast<QNetworkReply *>(sender());
	QByteArray replyData = reply->readAll();
	QNetworkReply::NetworkError error = reply->error();
	reply->deleteLater();
	if (error != QNetworkReply::NoError) {
		emit fetchError(tr("Network Error"));
		return;
	}

	// parse the data and notify the completion
	delete m_reader;
	m_reader = new Reader_1(replyData);
	emit fetched();
}

void Connector::slotTimeOut()
{
	// dispose the QNAM
	if (!m_nam)
		return;
	m_nam->deleteLater();
	m_nam = 0;

	// emit the error signal
	emit fetchError(tr("Network Timeout"));
}
